/**
 ****************************************************************************************************
 * @file        lcd.h
 * @author      LXP
 * @version     V1.0
 * @date        2024-07-31
 * @brief       4.3寸/7寸 TFTLCD(RGB屏) 驱动代码
 *
 ****************************************************************************************************/


#ifndef __LCD_H
#define __LCD_H



#include "stm32f4xx_hal.h"
#include "ltdc2.h"



/******************************************************************************************/
/* LCD重要参数集 */
typedef struct
{
    uint16_t width;     /* LCD 宽度 */
    uint16_t height;    /* LCD 高度 */
    uint16_t id;        /* LCD ID */
    uint8_t dir;        /* 横屏还是竖屏控制：0，竖屏；1，横屏。 */
    uint16_t wramcmd;   /* 开始写gram指令 */
    uint16_t setxcmd;   /* 设置x坐标指令 */
    uint16_t setycmd;   /* 设置y坐标指令 */
} _lcd_dev;

/* LCD参数 */
extern _lcd_dev lcddev; /* 管理LCD重要参数 */

/* LCD的画笔颜色和背景色 */
extern uint32_t  g_point_color;     /* 默认红色 */
extern uint32_t  g_back_color;      /* 背景颜色.默认为白色 */

/* LCD地址结构体 */
typedef struct
{
    volatile uint16_t LCD_REG;
    volatile uint16_t LCD_RAM;
} LCD_TypeDef;

/* RGB LCD模块LCD旋转方向枚举 */
typedef enum
{
    ATK_RGBLCD_LCD_DISP_DIR_0 = 0x00,   /* LCD顺时针旋转0°显示内容 */
    ATK_RGBLCD_LCD_DISP_DIR_90,         /* LCD顺时针旋转90°显示内容 */
    ATK_RGBLCD_LCD_DISP_DIR_180,        /* LCD顺时针旋转180°显示内容 */
    ATK_RGBLCD_LCD_DISP_DIR_270,        /* LCD顺时针旋转270°显示内容 */
} atk_rgblcd_lcd_disp_dir_t;
/* RGB LCD触摸IC类型枚举 */
typedef enum
{
    ATK_RGBLCD_TOUCH_TYPE_GTXX = 0x00,  /* GT9111、GT9147、GT9271 */
    ATK_RGBLCD_TOUCH_TYPE_FTXX,         /* FT5206 */
} atk_rgblcd_touch_type_t;
/* RGB LCD模块LCD显示数字模式枚举 */
//typedef enum
//{
//    ATK_RGBLCD_NUM_SHOW_NOZERO = 0x00,  /* 数字高位0不显示 */
//    ATK_RGBLCD_NUM_SHOW_ZERO,           /* 数字高位0显示 */
//} atk_rgblcd_num_mode_t;
/* LCD_BASE的详细解算方法:
 * 我们一般使用FMC的块1(BANK1)来驱动TFTLCD液晶屏(MCU屏), 块1地址范围总大小为256MB,均分成4块:
 * 存储块1(FMC_NE1)地址范围: 0x6000 0000 ~ 0x63FF FFFF
 * 存储块2(FMC_NE2)地址范围: 0x6400 0000 ~ 0x67FF FFFF
 * 存储块3(FMC_NE3)地址范围: 0x6800 0000 ~ 0x6BFF FFFF
 * 存储块4(FMC_NE4)地址范围: 0x6C00 0000 ~ 0x6FFF FFFF
 *
 * 我们需要根据硬件连接方式选择合适的片选(连接LCD_CS)和地址线(连接LCD_RS)
 * 阿波罗F429开发板使用FMC_NE1连接LCD_CS, FMC_A18连接LCD_RS ,16位数据线,计算方法如下:
 * 首先FMC_NE1的基地址为: 0x6000 0000;     NEX的基址为(x=1/2/3/4): 0x6000 0000 + (0x80000 * (x - 1))
 * FMC_A18对应地址值: 2^18 * 2 = 0x80000;    FMC_Ay对应的地址为(y = 0 ~ 25): 2^y * 2
 *
 * LCD->LCD_REG,对应LCD_RS = 0(LCD寄存器); LCD->LCD_RAM,对应LCD_RS = 1(LCD数据)
 * 则 LCD->LCD_RAM的地址为:  0x6000 0000 + 2^18 * 2 = 0x6008 0000
 *    LCD->LCD_REG的地址可以为 LCD->LCD_RAM之外的任意地址.
 * 由于我们使用结构体管理LCD_REG 和 LCD_RAM(REG在前,RAM在后,均为16位数据宽度)
 * 因此 结构体的基地址(LCD_BASE) = LCD_RAM - 2 = 0x6008 0000 -2
 *
 * 更加通用的计算公式为((片选脚FMC_NEX)X=1/2/3/4, (RS接地址线FMC_Ay)y=0~25):
 *          LCD_BASE = (0x6000 0000 + (0x80000 * (x - 1))) | (2^y * 2 -2)
 *          等效于(使用移位操作)
 *          LCD_BASE = (0x6000 0000 + (0x80000 * (x - 1))) | ((1 << y) * 2 -2)
 */
#define LCD_BASE        (uint32_t)((0X60000000 + (0x80000 * (LCD_FMC_NEX - 1))) | (((1 << LCD_FMC_AX) * 2) -2))
#define LCD             ((LCD_TypeDef *) LCD_BASE)

/******************************************************************************************/
/* LCD扫描方向和颜色 定义 */

/* 扫描方向定义 */
#define L2R_U2D         0           /* 从左到右,从上到下 */
#define L2R_D2U         1           /* 从左到右,从下到上 */
#define R2L_U2D         2           /* 从右到左,从上到下 */
#define R2L_D2U         3           /* 从右到左,从下到上 */

#define U2D_L2R         4           /* 从上到下,从左到右 */
#define U2D_R2L         5           /* 从上到下,从右到左 */
#define D2U_L2R         6           /* 从下到上,从左到右 */
#define D2U_R2L         7           /* 从下到上,从右到左 */

#define DFT_SCAN_DIR    L2R_U2D     /* 默认的扫描方向 */

/* 常用画笔颜色 */
#define WHITE           0xFFFF      /* 白色 */
#define BLACK           0x0000      /* 黑色 */
#define RED             0xF800      /* 红色 */
#define GREEN           0x07E0      /* 绿色 */
#define BLUE            0x001F      /* 蓝色 */
#define MAGENTA         0xF81F      /* 品红色/紫红色 = BLUE + RED */
#define YELLOW          0xFFE0      /* 黄色 = GREEN + RED */
#define CYAN            0x07FF      /* 青色 = GREEN + BLUE */

/* 非常用颜色 */
#define BROWN           0xBC40      /* 棕色 */
#define BRRED           0xFC07      /* 棕红色 */
#define GRAY            0x8430      /* 灰色 */
#define DARKBLUE        0x01CF      /* 深蓝色 */
#define LIGHTBLUE       0x7D7C      /* 浅蓝色 */
#define GRAYBLUE        0x5458      /* 灰蓝色 */
#define LIGHTGREEN      0x841F      /* 浅绿色 */
#define LGRAY           0xC618      /* 浅灰色(PANNEL),窗体背景色 */
#define LGRAYBLUE       0xA651      /* 浅灰蓝色(中间层颜色) */
#define LBBLUE          0x2B12      /* 浅棕蓝色(选择条目的反色) */

/******************************************************************************************/
/**********************************DAC背光定义************************************************/
//根据主板配置实际输出2.8V时关闭背光，输出0V时最亮
#define BL_VOLTAGE_MAX_VALUE	2400U
#define BL_VOLTAGE_STEP_VALUE	(BL_VOLTAGE_MAX_VALUE / 100.0)
#define BL_DAC_MAX_VALUE		4095
#define BL_DAC_STEP_VALUE		(BL_DAC_MAX_VALUE/3300.0)
extern DAC_HandleTypeDef hdac;
/******************************************************************************************/
/* 函数申明 */

//void lcd_wr_data(volatile uint16_t data);            /* LCD写数据 */
//void lcd_wr_regno(volatile uint16_t regno);          /* LCD写寄存器编号/地址 */
//void lcd_write_reg(uint16_t regno, uint16_t data);   /* LCD写寄存器的值 */

void lcd_init(void);                                 /* 初始化LCD */
void lcd_display_on(void);                           /* 开显示 */
void lcd_display_off(void);                          /* 关显示 */
//void lcd_scan_dir(uint8_t dir);                      /* 设置屏扫描方向 */
void lcd_display_dir(uint8_t dir);                   /* 设置屏幕显示方向 */
//void lcd_ssd_backlight_set(uint8_t pwm);             /* SSD1963 背光控制 */
void lcd_BackLight_adjust(uint8_t brightnessValue);	 /* 调节背光亮度，输入值0-100 */
void lcd_BackLight_on();							 /* 打开背光，默认最亮 */
void lcd_BackLight_off();							 /* 关闭背光 */

//void lcd_write_ram_prepare(void);                                                           /* 准备写GRAM */
//void lcd_set_cursor(uint16_t x, uint16_t y);                                                /* 设置光标 */
uint32_t lcd_read_point(uint16_t x, uint16_t y);                                            /* 读点(32位颜色,兼容LTDC) */
void lcd_draw_point(uint16_t x, uint16_t y, uint32_t color);                                /* 画点(32位颜色,兼容LTDC) */

void lcd_clear(uint16_t color);                                                             /* LCD清屏 */
void lcd_fill_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color);                   /* 填充实心圆 */
void lcd_draw_circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color);                  /* 画圆 */
void lcd_draw_hline(uint16_t x, uint16_t y, uint16_t len, uint16_t color);                  /* 画水平线 */
//void lcd_set_window(uint16_t sx, uint16_t sy, uint16_t width, uint16_t height);             /* 设置窗口 */
void lcd_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t color);          /* 纯色填充矩形(32位颜色,兼容LTDC) */
void lcd_color_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color);   /* 彩色填充矩形 */
void lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);     /* 画直线 */
void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);/* 画矩形 */

void lcd_show_char(uint16_t x, uint16_t y, uint8_t chr, uint8_t size, uint8_t mode, uint16_t color);
void lcd_show_num(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint16_t color);
void lcd_show_xnum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint8_t mode, uint16_t color);
void lcd_show_string(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t size, char *p, uint16_t color);

#endif

